package com.wyz.socket.core.impl.stealing;

import com.wyz.socket.core.api.IoProvider;
import com.wyz.socket.core.base.IoTask;
import com.wyz.socket.core.base.ProviderCallback;

import java.io.IOException;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class IoStealingSelectorProvider implements IoProvider {
    private final IoStealingSelectorThread[] threads;
    private final StealingService stealingService;

    public IoStealingSelectorProvider(int poolSize) throws IOException {
        IoStealingSelectorThread[] threads = new IoStealingSelectorThread[poolSize];
        for (int i = 0; i < poolSize; i++) {
            Selector selector = Selector.open();
            threads[i] = new IoStealingThread("IoProvider-StealingThread-" + (i + 1), selector);
        }
        StealingService stealingService = new StealingService(threads, 10);
        for (IoStealingSelectorThread thread : threads) {
            thread.setStealingService(stealingService);
            thread.setDaemon(false);
            thread.setPriority(Thread.MAX_PRIORITY);
            thread.start();
        }
        this.threads = threads;
        this.stealingService = stealingService;
    }


    @Override
    public void register(ProviderCallback callback) throws Exception {
        IoStealingSelectorThread notBusyThread = stealingService.getNotBusyThread();
        if (notBusyThread != null) {
            notBusyThread.register(callback);
        }
    }

    @Override
    public void unregister(SocketChannel channel) {
        if(!channel.isOpen()) return ;
        for (IoStealingSelectorThread item : threads
        ) {
            item.unregister(channel);
        }
    }

    @Override
    public void close() throws IOException {
        stealingService.close();
    }


    static class IoStealingThread extends IoStealingSelectorThread {

        public IoStealingThread(String name, Selector selector) {
            super(name, selector);
        }

        @Override
        protected boolean processTask(IoTask task) {
            return task.onProcess();
        }
    }
}
